home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 98 / Skunkware 98.iso / src / net / bind-contrib.tar.gz / bind-contrib.tar / contrib / nutshell / h2n < prev    next >
Encoding:
Text File  |  1996-10-25  |  19.3 KB  |  795 lines

  1. #!/usr/bin/perl
  2.  
  3. #NAME
  4. #
  5. #    h2n - Translate host table to name server file format
  6. #    $Date: 1996/10/25 04:57:47 $  $Revision: 8.1 $
  7. #
  8. #SYNOPSIS
  9. #
  10. #    h2n -d DOMAIN -n NET [options]
  11.  
  12. # Various defaults
  13. $Host = `hostname`;
  14. chop($Host);
  15. $Host =~ s/\..*//;               
  16. $doaliases = 1;
  17. $domx = 1;
  18. $dowks = 0;
  19. $dotxt = 0;
  20. $dontdodomains = 0;
  21. $Bootfile = "./named.boot";
  22. $Domain = "";
  23. $Hostfile = "/etc/hosts";
  24. $Commentfile = "";
  25. $Commentfileread = 0;
  26. $User = "root";
  27. $Pwd = `pwd`;
  28. $RespHost = "";
  29. $RespUser = "";
  30. $DefSerial = 1;
  31. $DefRefresh = 10800;
  32. $DefRetry = 3600;
  33. $DefExpire = 604800;
  34. $DefTtl = 86400;
  35. $DefMxWeight = 10;
  36. $Defsubnetmask = "";
  37. $ForceSerial = -1;
  38. $UseDateInSerial = 0;
  39. $DateSerial = 0;
  40.  
  41. push(@bootmsgs, "primary\t0.0.127.IN-ADDR.ARPA db.127.0.0\n");
  42.  
  43. &PARSEARGS(@ARGV);
  44. &FIXUP;
  45.  
  46. open(HOSTS, $Hostfile) || die "can not open $Hostfile";
  47.  
  48. LINE: while(<HOSTS>){
  49.     next if /^#/;        # skip comment lines
  50.     next if /^$/;       # skip empty lines
  51.     chop;                # remove the trailing newline
  52.     tr/A-Z/a-z/;     # translate to lower case 
  53.  
  54.     ($data,$comment) = split('#', $_, 2);
  55.     ($addr, $names) = split(' ', $data, 2);
  56.     if ($names =~ /^[ \t]*$/) {
  57.     print STDERR "Bad line in hosts file ignored '$_'\n";
  58.     next LINE;
  59.     }
  60.  
  61.     # Match -e args
  62.     foreach $netpat (@elimpats){
  63.     next LINE if (/[.\s]$netpat/);
  64.     }
  65.  
  66.     # Process -c args
  67.     foreach $netpat (@cpats){
  68.     if (/\.$netpat/) {
  69.         ($canonical, $aliases) = split(' ', $names, 2);
  70.         $canonical =~ s/\.$netpat//; 
  71.         if($Cnames{$canonical} != 1){
  72.             printf DOMAIN "%-20s IN  CNAME %s.%s.\n", 
  73.                $canonical, $canonical, $cpatrel{$netpat};
  74.         $Cnames{$canonical} = 1;
  75.         }
  76.         next LINE;
  77.     }
  78.     }
  79.  
  80.     # Check that the address is in the address list.
  81.     $match = 'none';
  82.     foreach $netpat (@Netpatterns){
  83.     $match = $netpat, last if ($addr =~ /^$netpat\./);
  84.     }
  85.     next if ($match eq 'none');
  86.  
  87.     ($canonical, $aliases) = split(' ', $names, 2);  # separate out aliases
  88.     next if ($dontdodomains && $canonical =~ /\./);  # skip domain names
  89.     $canonical =~ s/$Domainpattern//;     # strip off domain if there is one
  90.     $Hosts{$canonical} .= $addr . " ";    # index addresses by canonical name
  91.     $Aliases{$addr} .= $aliases . " ";    # index aliases by address
  92.     $Comments{"$canonical-$addr"} = $comment;
  93.  
  94.     # Print PTR records
  95.     $file = $Netfiles{$match};
  96.     printf $file "%-30s\tIN  PTR   %s.%s.\n", 
  97.        &REVERSE($addr), $canonical, $Domain;
  98. }
  99.  
  100. #
  101. # Go through the list of canonical names.
  102. # If there is more than 1 address associated with the
  103. # name, it is a multi-homed host.  For each address 
  104. # look up the aliases since the aliases are associated 
  105. # with the address, not the canonical name.
  106. #
  107. foreach $canonical (keys %Hosts){
  108.     @addrs = split(' ', $Hosts{$canonical});
  109.     $numaddrs = $#addrs + 1;
  110.     foreach $addr (@addrs) {
  111.     #
  112.     # Print address record for canonical name.
  113.     #
  114.     if($Cnames{$canonical} != 1){
  115.         printf DOMAIN "%-20s IN  A     %s\n", $canonical, $addr;
  116.     } else {
  117.         print STDERR "$canonical - can't create A record because CNAME exists for name.\n";
  118.     }
  119.     #
  120.     # Print cname or address records for each alias.
  121.     # If this is a multi-homed host, print an address
  122.     # record for each alias.  If this is a single address
  123.     # host, print a cname record.
  124.     #
  125.     if ($doaliases) {
  126.         @aliases = split(' ', $Aliases{$addr});
  127.         foreach $alias (@aliases){
  128.         #
  129.         # Skip over the alias if the alias and canonical
  130.         # name only differ in that one of them has the
  131.         # domain appended to it.
  132.         #
  133.             next if ($dontdodomains && $alias =~ /\./); # skip domain names
  134.         $alias =~ s/$Domainpattern//;
  135.         if($alias eq $canonical){
  136.             next;
  137.         }
  138.  
  139.                 $aliasforallnames = 0;
  140.         if($numaddrs > 1){
  141.                     #
  142.                     # If alias exists for *all* addresses of this host, we
  143.                     # can use a CNAME instead of an address record.
  144.                     #
  145.                     $aliasforallnames = 1;
  146.                     $xalias = $alias . " ";  # every alias ends with blank
  147.                     @xaddrs = split(' ', $Hosts{$canonical});
  148.                     foreach $xaddr (@xaddrs) {
  149.                         if(!($Aliases{$xaddr} =~ /\b$xalias/)) {
  150.                             $aliasforallnames = 0;
  151.                         }
  152.                     }
  153.                 }
  154.  
  155.         if(($numaddrs > 1) && !$aliasforallnames){
  156.             printf DOMAIN "%-20s IN  A     %s\n", $alias, $addr;
  157.         } else {
  158.             #
  159.             # Flag aliases that have already been used
  160.             # in CNAME records or have A records.
  161.             #
  162.             if(($Cnames{$alias} != 1) && (!$Hosts{$alias})){
  163.             printf DOMAIN "%-20s IN  CNAME %s.%s.\n", 
  164.                    $alias, $canonical, $Domain;
  165.             $Cnames{$alias} = 1;
  166.             } else {
  167.             print STDERR "$alias - CNAME or A exists already; alias ignored\n";
  168.             }
  169.         }
  170.  
  171.                 if($aliasforallnames){
  172.                     #
  173.                     # Since a CNAME record was created, remove this
  174.                     # name from the alias list so we don't encounter
  175.                     # it again for the next address of this host.
  176.                     #
  177.                     $xalias = $alias . " ";  # every alias ends with blank
  178.                     @xaddrs = split(' ', $Hosts{$canonical});
  179.                     foreach $xaddr (@xaddrs) {
  180.                         $Aliases{$xaddr} =~ s/\b$xalias//;
  181.                     }
  182.                 }
  183.         }
  184.     }
  185.     }
  186.     if ($domx) {
  187.     &MX($canonical, @addrs);
  188.     }
  189.     if ($dotxt) {
  190.     &TXT($canonical, @addrs);
  191.     }
  192.     if ($Commentfile ne "") {
  193.     &DO_COMMENTS($canonical, @addrs);
  194.     }
  195. }
  196.  
  197. # Deal with spcl's
  198. if (-r "spcl.$Domainfile") {
  199.     print DOMAIN "\$INCLUDE spcl.$Domainfile\n";
  200. }
  201. foreach $n (@Networks) {
  202.     if (-r "spcl.$n") {
  203.     $file = "DB.$n";
  204.     print $file "\$INCLUDE spcl.$n\n";
  205.     }
  206. }
  207.  
  208. # generate boot.* files
  209. &GEN_BOOT;
  210.  
  211. exit;
  212.  
  213.  
  214. #
  215. # Generate resource record data for
  216. # strings from the commment field that
  217. # are found in the comment file (-C).
  218. #
  219. sub DO_COMMENTS {
  220.     local($canonical, @addrs) = @_;
  221.     local(*F, @c, $c, $a, $comments);
  222.     
  223.     if (!$Commentfileread) {
  224.     open(F, $Commentfile) || die "Unable to open file $Commentfile: $!";
  225.     $Commentfileread++;
  226.     while (<F>) {
  227.         chop;
  228.         ($key, $c) = split(':', $_, 2);
  229.         $CommentRRs{$key} = $c;
  230.     }
  231.     close(F);
  232.     }
  233.     
  234.     foreach $a (@addrs) {
  235.     $key = "$canonical-$a";
  236.     $comments .= " $Comments{$key}";
  237.     }
  238.  
  239.     @c = split(' ', $comments);
  240.     foreach $c (@c) {
  241.     if($CommentRRs{$c}){
  242.         printf DOMAIN "%-20s %s\n", $canonical, $CommentRRs{$c};
  243.     }
  244.     }
  245. }
  246.  
  247.  
  248. #
  249. # Generate MX record data
  250. #
  251. sub MX {
  252.     local($canonical, @addrs) = @_;
  253.     local($first, $a, $key, $comments);
  254.  
  255.     if($Cnames{$canonical}){
  256.     print STDERR "$canonical - can't create MX record because CNAME exists for name.\n";
  257.     return;
  258.     }
  259.     $first = 1;
  260.  
  261.     foreach $a (@addrs) {
  262.     $key = "$canonical-$a";
  263.     $comments .= " $Comments{$key}";
  264.     }
  265.     
  266.     if ($comments !~ /\[no smtp\]/) {
  267.         # Add WKS if requested
  268.         if ($dowks) {
  269.         foreach $a (@addrs) {
  270.             printf DOMAIN "%-20s IN  WKS   %s TCP SMTP\n", $canonical, $a;
  271.         }
  272.         }
  273.     printf DOMAIN "%-20s IN  MX    %s %s.%s.\n", $canonical, $DefMxWeight, 
  274.            $canonical, $Domain; 
  275.     $first = 0;
  276.     }
  277.     if ($#Mx >= 0) {
  278.     foreach $a (@Mx) {
  279.         if ($first) {
  280.         printf DOMAIN "%-20s IN  MX    %s\n", $canonical, $a; 
  281.         $first = 0;
  282.         } else {
  283.         printf DOMAIN "%-20s IN  MX    %s\n", "", $a; 
  284.         }
  285.     }
  286.     }
  287.  
  288. }
  289.  
  290.  
  291. #
  292. # Generate TXT record data
  293. #
  294. sub TXT {
  295.     local($canonical, @addrs) = @_;
  296.     local($a, $key, $comments);
  297.  
  298.     foreach $a (@addrs) {
  299.     $key = "$canonical-$a";
  300.     $comments .= " $Comments{$key}";
  301.     }
  302.     $comments =~ s/\[no smtp\]//g;
  303.     $comments =~ s/^\s*//;
  304.     $comments =~ s/\s*$//;
  305.     
  306.     if ($comments ne "") {
  307.     printf DOMAIN "%s IN  TXT   \"%s\"\n", $canonical, $comments;
  308.     }
  309. }
  310.  
  311.  
  312. #
  313. # Create the SOA record at the beginning of the file
  314. #
  315. sub MAKE_SOA {
  316.     local($fname, $file) = @_;
  317.     local($s);
  318.  
  319.     if ( -s $fname) {
  320.     open($file, "$fname") || die "Unable to open $fname: $!";
  321.     $_ = <$file>;
  322.     chop;
  323.     if (/\($/) {
  324.         if (! $soa_warned) {
  325.         print STDERR "Converting SOA format to new style.\n";
  326.         $soa_warned++;
  327.         }
  328.         if ($ForceSerial > 0) {
  329.         $Serial = $ForceSerial;
  330.         } else {
  331.         ($Serial, $junk) = split(' ', <$file>, 2);
  332.         $Serial++;
  333.                 if($UseDateInSerial && ($DateSerial > $Serial)){
  334.                     $Serial = $DateSerial;
  335.                 }
  336.         }
  337.         if (!defined($Refresh)) {
  338.         ($Refresh, $junk) = split(' ', <$file>, 2);
  339.         ($Retry, $junk) = split(' ', <$file>, 2);
  340.         ($Expire, $junk) = split(' ', <$file>, 2);
  341.         ($Ttl, $junk) = split(' ', <$file>, 2);
  342.         }
  343.     } else {
  344.         split(' ');
  345.         if ($#_ == 11) {
  346.         if ($ForceSerial > 0) {
  347.             $Serial = $ForceSerial;
  348.         } else {
  349.             $Serial = ++@_[6];
  350.                     if($UseDateInSerial && ($DateSerial > $Serial)){
  351.                         $Serial = $DateSerial;
  352.                     }
  353.         }
  354.         if (!defined($Refresh)) {
  355.             $Refresh = @_[7];
  356.             $Retry = @_[8];
  357.             $Expire = @_[9];
  358.             $Ttl = @_[10];
  359.         }
  360.         } else {
  361.         print STDERR "Improper format SOA in $fname.\n";
  362.         print STDERR "I give up ... sorry.\n";
  363.         exit(1);
  364.         }
  365.     }
  366.     close($file);
  367.     } else {
  368.     if ($ForceSerial > 0) {
  369.         $Serial = $ForceSerial;
  370.     } else {
  371.         $Serial = $DefSerial;
  372.     }
  373.     if (!defined($Refresh)) {
  374.         $Refresh = $DefRefresh;
  375.         $Retry = $DefRetry;
  376.         $Expire = $DefExpire;
  377.         $Ttl = $DefTtl;
  378.     }
  379.     close($file);
  380.     }
  381.  
  382.     open($file, "> $fname") || die "Unable to open $fname: $!";
  383.  
  384.     print $file "\@ IN  SOA $RespHost $RespUser ";
  385.     print $file "( $Serial $Refresh $Retry $Expire $Ttl )\n";
  386.     foreach $s (@Servers) {
  387.     print $file "  IN  NS  $s\n";
  388.     }
  389.     print $file "\n";
  390. }
  391.  
  392.  
  393. #
  394. # Reverse the octets of an IP address and append
  395. # in-addr.arpa.
  396. #
  397. sub REVERSE {
  398.     join('.', reverse(split('\.', $_[0]))) . '.IN-ADDR.ARPA.';
  399. }
  400.  
  401.  
  402. #
  403. # Establish what we will be using for SOA records
  404. #
  405. sub FIXUP {
  406.     local($s);
  407.  
  408.     if ($Host =~ /\./) {
  409.     $RespHost = "$Host.";
  410.     } else {
  411.     $RespHost = "$Host.$Domain.";
  412.     }
  413.     $RespHost =~ s/\.\././g;
  414.  
  415.     if ($User =~ /@/) {                # -u user@...
  416.     if ($User =~ /\./) {
  417.         $RespUser = "$User.";        # -u user@terminator.movie.edu
  418.     } else {
  419.         $RespUser = "$User.$Domain.";     # -u user@terminator
  420.     }
  421.     $RespUser =~ s/@/./;
  422.     } elsif ($User =~ /\./) {
  423.     $RespUser = "$User.";            # -u user.terminator.movie.edu
  424.     } else {
  425.     $RespUser = "$User.$RespHost";        # -u user
  426.     }
  427.     $RespUser =~ s/\.\././g;            # Strip any ".."'s to "."
  428.  
  429.     # Clean up nameservers
  430.     if (!defined(@Servers)) {
  431.     push(@Servers, "$Host.$Domain.");
  432.     } else {
  433.     foreach $s (@Servers) {
  434.         if ($s !~ /\./) {
  435.         $s .= ".$Domain";
  436.         }
  437.         if ($s !~ /\.$/) {
  438.         $s .= ".";
  439.         }
  440.     }
  441.     }
  442.  
  443.     # Clean up MX hosts
  444.     foreach $s (@Mx) {
  445.     $s =~ s/:/ /;
  446.     if ($s !~ /\./) {
  447.         $s .= ".$Domain";
  448.     }
  449.     if ($s !~ /\.$/) {
  450.         $s .= ".";
  451.     }
  452.     }
  453.  
  454.     # Now open boot file and print saved data
  455.     open(BOOT, "> $Bootfile")  || die "can not open $Bootfile";
  456.     print BOOT "\ndirectory $Pwd\n";
  457.     foreach $line (@bootmsgs) {
  458.     print BOOT $line;
  459.     }
  460.     print BOOT "cache\t. db.cache\n";
  461.     if (-r "spcl.boot") {
  462.         print BOOT "include\tspcl.boot\n";
  463.     }
  464.  
  465.     # Go ahead and start creating files and making SOA's
  466.     foreach $i (@makesoa) {
  467.     ($x1, $x2) = split(' ', $i);
  468.     &MAKE_SOA($x1, $x2);
  469.     }
  470.     printf DOMAIN "%-20s IN  A     127.0.0.1\n", "localhost";
  471.     
  472.     $file = "DB.127.0.0.1";
  473.     &MAKE_SOA("db.127.0.0", $file);
  474.     printf $file "%-30s\tIN  PTR   localhost.\n", &REVERSE("127.0.0.1");
  475.     close($file);
  476. }
  477.  
  478.  
  479. sub PARSEARGS {
  480.     local(@args) = @_;
  481.     local($i, $net, $subnetmask, $option, $tmp1);
  482.     local(*F, $file, @newargs, @targs);
  483.     local($sec,$min,$hour,$mday,$mon,$year,$rest);
  484.  
  485.     $i = 0;
  486.     while ($i <= $#args){
  487.     $option = $args[$i];
  488.     if($option eq "-d"){
  489.             if ($Domain ne "") {
  490.         print STDERR "Only one -d option allowed.\n";
  491.         print STDERR "I give up ... sorry.\n";
  492.         exit(1);
  493.             }
  494.         $Domain = $args[++$i];
  495.         $Domainpattern = "." . $Domain;
  496.         $Domainpattern =~ s/\./\\./g;        # for stripping off domain
  497.  
  498.         # Add entry to the boot file.
  499.         $Domainfile = $Domain;
  500.         $Domainfile =~ s/\..*//;
  501.         push(@makesoa, "db.$Domainfile DOMAIN");
  502.         push(@bootmsgs, "primary\t$Domain db.$Domainfile\n");
  503.  
  504.     } elsif ($option eq "-f"){
  505.         $file = $args[++$i];
  506.         open(F, $file) || die "Unable to open args file $file: $!";
  507.         while (<F>) {
  508.         next if (/^#/);
  509.         next if (/^$/);
  510.         chop;
  511.         @targs = split(' ');
  512.         push(@newargs, @targs);
  513.         }
  514.         close(F);
  515.         &PARSEARGS(@newargs);
  516.  
  517.     } elsif ($option eq "-z"){
  518.         $Bootsecsaveaddr = $args[++$i];
  519.         if (!defined($Bootsecaddr)) {
  520.         $Bootsecaddr = $Bootsecsaveaddr;
  521.         }
  522.  
  523.     } elsif ($option eq "-Z"){
  524.         $Bootsecaddr = $args[++$i];
  525.         if (!defined($Bootsecsaveaddr)) {
  526.         $Bootsecsaveaddr = $Bootsecaddr;
  527.         }
  528.  
  529.     } elsif ($option eq "-b"){
  530.         $Bootfile = $args[++$i];
  531.  
  532.     } elsif ($option eq "-A"){
  533.         $doaliases = 0;
  534.  
  535.     } elsif ($option eq "-M"){
  536.         $domx = 0;
  537.  
  538.     } elsif ($option eq "-w"){
  539.         $dowks = 1;
  540.  
  541.     } elsif ($option eq "-D"){
  542.         $dontdodomains = 1;
  543.  
  544.     } elsif ($option eq "-t"){
  545.         $dotxt = 1;
  546.  
  547.     } elsif ($option eq "-u"){
  548.         $User = $args[++$i];
  549.  
  550.     } elsif ($option eq "-s"){
  551.         while ($args[++$i] !~ /^-/ && $i <= $#args) {
  552.         push(@Servers, $args[$i]);
  553.         }
  554.         $i--;
  555.  
  556.     } elsif ($option eq "-m"){
  557.         if ($args[++$i] !~ /:/) {
  558.         print STDERR "Improper format for -m option ignored ($args[$i]).\n";
  559.         }
  560.         push(@Mx, $args[$i]);
  561.  
  562.     } elsif ($option eq "-c"){
  563.         $tmp1 = $args[++$i];
  564.         if ($tmp1 !~ /\./) {
  565.         $tmp1 .= ".$Domain";
  566.         }
  567.             if ($Domain eq $tmp1) {
  568.         print STDERR "Domain for -c option must not match domain for -d option.\n";
  569.         print STDERR "I give up ... sorry.\n";
  570.         exit(1);
  571.             }
  572.         $tmp2 = $tmp1;
  573.         $tmp2 =~ s/\./\\./g; 
  574.         $cpatrel{$tmp2} = $tmp1;
  575.         push(@cpats, $tmp2);
  576.  
  577.     } elsif ($option eq "-e"){
  578.         $tmp1 = $args[++$i];
  579.         if ($tmp1 !~ /\./) {
  580.         $tmp1 .= ".$Domain";
  581.         }
  582.         $tmp1 =~ s/\./\\./g; 
  583.         push(@elimpats, $tmp1);
  584.  
  585.     } elsif ($option eq "-h"){
  586.         $Host = $args[++$i];
  587.  
  588.     } elsif ($option eq "-o"){
  589.         if (   $args[++$i] !~ /^[:\d]*$/ 
  590.         || split(':', $args[$i]) != 4) {
  591.         print STDERR "Improper format for -o ($args[$i]).\n";
  592.         print STDERR "I give up ... sorry.\n";
  593.         exit(1);
  594.         }
  595.         ($DefRefresh, $DefRetry, $DefExpire, $DefTtl) = split(':', $args[$i]);
  596.  
  597.     } elsif ($option eq "-i"){
  598.         $ForceSerial = $args[++$i];
  599.  
  600.     } elsif ($option eq "-H"){
  601.         $Hostfile = $args[++$i];
  602.         if (! -r $Hostfile || -z $Hostfile) {
  603.         print STDERR "Invalid file specified for -H ($Hostfile).\n";
  604.         print STDERR "I give up ... sorry.\n";
  605.         exit(1);
  606.         }
  607.  
  608.     } elsif ($option eq "-C"){
  609.         $Commentfile = $args[++$i];
  610.         if (! -r $Commentfile || -z $Commentfile) {
  611.         print STDERR "Invalid file specified for -C ($Commentfile).\n";
  612.         print STDERR "I give up ... sorry.\n";
  613.         exit(1);
  614.         }
  615.  
  616.     } elsif ($option eq "-N"){
  617.         $Defsubnetmask = $args[++$i];
  618.         if (   $Defsubnetmask !~ /^[.\d]*$/ 
  619.         || split('\.', $Defsubnetmask) != 4) {
  620.         print STDERR "Improper subnet mask ($Defsubnetmask).\n";
  621.         print STDERR "I give up ... sorry.\n";
  622.         exit(1);
  623.         }
  624.         if ($#Networks >= 0) {
  625.         print STDERR "Hmm, -N option should probably be specified before any -n options.\n";
  626.         }
  627.  
  628.     } elsif ($option eq "-n"){
  629.         ($net, $subnetmask) = split(':',$args[++$i]);
  630.         if ($subnetmask eq "") {
  631.         foreach $tmp1 (&SUBNETS($net, $Defsubnetmask)) {
  632.             &BUILDNET($tmp1);
  633.         }
  634.         } else {
  635.         if (   $subnetmask !~ /^[.\d]*$/ 
  636.             || split('\.', $subnetmask) != 4) {
  637.             print STDERR "Improper subnet mask ($subnetmask).\n";
  638.             print STDERR "I give up ... sorry.\n";
  639.             exit(1);
  640.         }
  641.         foreach $tmp1 (&SUBNETS($net, $subnetmask)) {
  642.             &BUILDNET($tmp1);
  643.         }
  644.         }
  645.  
  646.     } elsif ($option eq "-y"){
  647.             $UseDateInSerial = 1;
  648.             ($sec,$min,$hour,$mday,$mon,$year,$rest) = localtime(time);
  649.             $DateSerial = ($mday * 100) + 
  650.                           (($mon + 1) * 10000) + 
  651.                           (($year + 1900) * 1000000);
  652.     } elsif ($option eq "-1"){
  653.         print STDERR "Option -1 is obsolete ... ignored.\n";
  654.  
  655.     } elsif ($option eq "-F"){
  656.         print STDERR "Option -F is now the default (and only) way ... ignored.\n";
  657.  
  658.     } else {
  659.         if($option =~ /^-.*/){
  660.         print STDERR "Unknown option: $option ... ignored.\n";
  661.         }
  662.     }
  663.     $i++;
  664.     }
  665.     
  666.     if (!defined(@Networks) || $Domain eq "") {
  667.     print STDERR "Must specify one -d and at least one -n.\n";
  668.     print STDERR "I give up ... sorry.\n";
  669.     exit(1);
  670.     }
  671. }
  672.  
  673.  
  674. sub BUILDNET {
  675.     local($net) = @_;
  676.  
  677.     push(@Networks, $net);
  678.     #
  679.     # Create pattern to match against.  
  680.     # The dots must be changed to \. so they 
  681.     # aren't used as wildcards.
  682.     #
  683.     $netpat = $net;
  684.     $netpat =~ s/\./\\./g;
  685.     push(@Netpatterns, $netpat);
  686.  
  687.     #
  688.     # Create db files for PTR records.
  689.     # Save the file names in an array for future use.
  690.     #
  691.     $netfile = "DB.$net";
  692.     $Netfiles{$netpat} = $netfile;
  693.     push(@makesoa, "db.$net $netfile");
  694.  
  695.     # Add entry to the boot file.
  696.     $revaddr = &REVERSE($net);
  697.     chop($revaddr);   # remove trailing dot
  698.     push(@bootmsgs, "primary $revaddr db.$net\n");
  699. }
  700.  
  701.  
  702. #
  703. # Calculate all the subnets from a network number and mask.
  704. # This was originally written for awk, not perl.
  705. #
  706. sub SUBNETS {
  707.     local($network, $mask) = @_;
  708.     local(@ans, @net, @mask, $buf, $number, $i, $j, $howmany);
  709.  
  710.     @net = split(/\./, $network);
  711.     @mask = split(/\./, $mask);
  712.     $number = '';
  713.     #
  714.     # Only expand bytes 1, 2, or 3
  715.     # for DNS purposes
  716.     #
  717.     for ($i = 0; $i < 3; $i++) {
  718.     if ($mask[$i] == 255) {
  719.         $number = $number . $net[$i] . '.';
  720.     } elsif (($mask[$i] == 0) || $mask[$i] eq '') {
  721.         push(@ans, $network);
  722.         last;
  723.     } else {
  724.         #
  725.         # This should be done as a bit-wise or
  726.         # but awk does not have an or symbol
  727.         #
  728.         $howmany = 255 - $mask[$i];
  729.         for ($j = 0; $j <= $howmany; $j++) {
  730.         if ($net[$i] + $j <= 255) {
  731.             $buf = sprintf("%s%d", $number, $net[$i] + $j);
  732.             push(@ans, $buf);
  733.         }
  734.         }
  735.         last;
  736.     }
  737.     }
  738.  
  739.     if ($#ans == -1) {
  740.     push(@ans, $network);
  741.     }
  742.     
  743.     @ans;
  744. }
  745.  
  746.  
  747. sub GEN_BOOT {
  748.     local(*F, $revaddr, $n);
  749.  
  750.     if (! -e "boot.cacheonly") {
  751.     open(F, ">boot.cacheonly") || die "Unable to open boot.cacheonly: $!";
  752.     print F "directory\t$Pwd\n";
  753.     print F "primary\t\t0.0.127.IN-ADDR.ARPA    db.127.0.0\n";
  754.     print F "cache\t\t.                       db.cache\n";
  755.         if (-r "spcl.cacheonly") {
  756.             printf F "include\t\tspcl.cacheonly\n";
  757.         }
  758.     close(F);
  759.     }
  760.     
  761.     if (defined($Bootsecaddr)) {
  762.     open(F, ">boot.sec") || die "Unable to open boot.sec: $!";
  763.     print  F "directory\t$Pwd\n";
  764.     print  F "primary\t\t0.0.127.IN-ADDR.ARPA    db.127.0.0\n";
  765.     printf F "secondary\t%-23s $Bootsecaddr\n", $Domain;
  766.     foreach $n (@Networks) {
  767.         $revaddr = &REVERSE($n);
  768.         chop($revaddr);
  769.         printf F "secondary\t%-23s $Bootsecaddr\n", $revaddr;
  770.     }
  771.     print  F "cache\t\t.                       db.cache\n";
  772.         if (-r "spcl.boot") {
  773.             printf F "include\t\tspcl.boot\n";
  774.         }
  775.     close(F);
  776.  
  777.     open(F, ">boot.sec.save") || die "Unable to open boot.sec.save: $!";
  778.     print  F "directory\t$Pwd\n";
  779.     print  F "primary\t\t0.0.127.IN-ADDR.ARPA    db.127.0.0\n";
  780.     printf F "secondary\t%-23s $Bootsecsaveaddr db.%s\n", 
  781.            $Domain, $Domainfile;
  782.     foreach $n (@Networks) {
  783.         $revaddr = &REVERSE($n);
  784.         chop($revaddr);
  785.         printf F "secondary\t%-23s $Bootsecsaveaddr db.%s\n", 
  786.            $revaddr, $n;
  787.     }
  788.     print  F "cache\t\t.                       db.cache\n";
  789.         if (-r "spcl.boot") {
  790.             printf F "include\t\tspcl.boot\n";
  791.         }
  792.     close(F);
  793.     }
  794. }
  795.